/*
Copyright (C) 2011 by the PSVN Research Group, University of Alberta
*/

#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <time.h>


/* generate a state using backwards moves from the goal
   returns non-zero on success, 0 on failure

   only uses the first goal state - if there are more goal states, you
   may want to change this to count them and then select a random goal

   NOTE THAT THIS MAY GENERATE SYNTACTICALLY CORRECT BUT INVALID
   STATES IF NOT ALL STATES ARE VALID AND AT LEAST ONE GAME RULE
   ASSIGNS A CONSTANT TO A STATE VARIABLE WHICH IS EITHER A LABEL OR
   UNSPECIFIED ON THE LEFT HAND SIDE */
int random_state( state_t *state )
{
  int i, max_i, num_moves, j;
  func_ptr iter;
  int rules[ bw_max_children ];
  state_t child, *s, *c, *t;

  s = state;
  c = &child;

  random_goal_state( state );
  max_i = 1000 + random() % 10;
  for( i = 0; i < max_i; ++i ) {

    num_moves = 0;
    init_bwd_iter( iter );
    while( ( rules[ num_moves ] = next_bwd_iter( iter, s ) ) >= 0 ) {
      ++num_moves;
    }

    if( num_moves == 0 ) {
      printf( "no moves at state " );
      print_state( stdout, s );
      printf( "\n" );
      if( i ) {
	printf( "parent " );
	print_state( stdout, c );
	printf( "\n" );
      }
      exit( -1 );
    }

    j = random() % num_moves;
    apply_bwd_rule( rules[ j ], s, c );
    t = s;
    s = c;
    c = t;
  }

  if( s != state ) {
    copy_state( state, s );
  }

  return 0;
}

int main( int argc, char **argv )
{
  state_t state;
  int num_trials = 100;
  int trials;

  srandom( time( NULL ) );
  for( trials = 0; trials < num_trials; ++trials ) {

    random_state( &state );
    print_state( stdout, &state );
    printf( "\n" );
  }

  return 0;
}
